﻿#include "BNSPlayerApp.h"

extern "C"
{
#include "libavcodec/avcodec.h"
#include <libavutil/avutil.h>
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
#include "libavfilter/avfilter.h"
}

#include "Decoder.h"
#include <QGuiApplication>
#include <QFileDialog>
#include "AppData.h"
#include <QCryptographicHash>

BNSPlayerApp::BNSPlayerApp(QObject *parent)
    : QObject{parent}
{
    avdevice_register_all();

    // 打开并跳转到上次关闭前的文件和时间点。
    std::string lastFilename;
    if(appData.get("lastFile", lastFilename)) {
        openVideoFile(QUrl::fromLocalFile(QString::fromStdString(lastFilename)));
    }
}

QString timeToString(double seconds) 
{
    // 将秒数转换为整数，分离出小时、分钟和秒
    int totalSeconds = static_cast<int>(seconds);
    int hours = totalSeconds / 3600;
    int minutes = (totalSeconds % 3600) / 60;
    int secs = totalSeconds % 60;

    // 使用 QString 的格式化功能来生成字符串
    return QString("%1:%2:%3")
            .arg(hours, 2, 10, QChar('0'))
            .arg(minutes, 2, 10, QChar('0'))
            .arg(secs, 2, 10, QChar('0'));
}

int BNSPlayerApp::openVideoFile(const QUrl &file)
{
    if (m_decoder) {
        qInfo() << "Destroying the deocder...";
        delete m_decoder;
        m_decoder = nullptr;
    }

    qInfo() << "Building the decoder...";
    Decoder* decoder = new Decoder(this);
    connect(decoder, &Decoder::stateChanged, this, &BNSPlayerApp::onDecoderStateChanged, Qt::QueuedConnection);
    connect(decoder, &Decoder::currentPositionChanged, this, &BNSPlayerApp::onDecoderPosChanged, Qt::QueuedConnection);

    // decoder->setVideoFrameRenderer(m_mainWindow.ui->frameRenderer);

    qInfo() << "Decoding the file: " << file;
    if(!decoder->start(file.toLocalFile())) {
        qWarning() << "Failed to started decodec file: " << file;
        return -1;
    }

    m_decoder = decoder;

    // 将播放文件记录为最后一次播放的文件
    appData.set("lastFile", file.toLocalFile().toStdString());

    // 尝试从历史记录中读取该文件的最后一次播放进度并跳转到该时间点
    double timepoint = 0.0;
    if(appData.playHistory(file.toLocalFile().toStdString(), timepoint)) {
        m_decoder->seek(timepoint);
    }

    // UI 隐藏中央控制面板, 设置播放按钮样式
//    m_mainWindow.ui->centerPanel->setVisible(false);
//    auto b = m_mainWindow.blockSignals(true);
//    m_mainWindow.ui->PNPBtn->setChecked(true);
//    m_mainWindow.ui->PNPBtn->setIcon(QIcon(":/resources/icons/pause.svg"));
//    m_mainWindow.ui->PNPBtn->setProperty("iconName", "pause");
//    m_mainWindow.blockSignals(b);

    return 0;
}

bool BNSPlayerApp::isPlaying() const
{
    return m_decoder && m_decoder->state() == Decoder::RunningState;
}

void BNSPlayerApp::pause()
{
    if(m_decoder && m_decoder->state() == Decoder::RunningState) {
        m_decoder->pause();
    }
}

void BNSPlayerApp::play()
{
    if(m_decoder && m_decoder->state() == Decoder::PausedState) {
        m_decoder->resume();
    }
}

void BNSPlayerApp::openFileFromSysDialog()
{
//    QString filter = "Media Files (*.mp4 *.avi *.mkv *.mp3 *.wav);;All Files (*.*)";
//    std::string dir;
//    appData.get("lastOpenedDir", dir);

//    auto filename = QFileDialog::getOpenFileName(&m_mainWindow, tr(u8"选择一个视频或音频文件..."), QString::fromStdString(dir), filter);
//    qDebug() << "The user open the file: " << filename;

//    QFileInfo fileInfo(filename);
//    qDebug() << fileInfo.absolutePath();

//    appData.set("lastOpenedDir", fileInfo.absolutePath().toStdString());

//    openVideoFile(QUrl::fromLocalFile(fileInfo.absoluteFilePath()));
}

void BNSPlayerApp::onUIProcessSliderChanged(double pos)
{
    if(!m_decoder || m_decoder->fileDuration() == 0.0) {
        return;
    }

    m_decoder->seek(pos * m_decoder->fileDuration());
}

void BNSPlayerApp::onDecoderPosChanged()
{
    // UI 设置进度条和时间
    auto curSec = m_decoder->currentPos();
    auto totalSec = m_decoder->fileDuration();
    auto curSecStr = timeToString(curSec);
    auto totalSecStr = timeToString(totalSec);

    // 保存文件播放记录点。
    double lastTimepoint = 0.0;
    std::string filename = m_decoder->videoFile().toStdString();
    if(appData.playHistory(filename, lastTimepoint)) {
        if(std::abs(curSec - lastTimepoint) >= 1.0)
            appData.setPlayHistory(filename, curSec);
    }    
    else {
        appData.setPlayHistory(filename, curSec);
    }
}

void BNSPlayerApp::onDecoderStateChanged(Decoder::DecodcState newState, QString desc)
{
    emit isPlayingChanged();
}
